import role from '@/assets/imgs/role.png'
import role2 from '@/assets/imgs/role2.png'
import wall from '@/assets/imgs/wall.png'
interface wall {
    pointStartX: number,
    pointStartY: number,
    wallW: number,
    wallH: number,
}
// 场景类
export default class CustomCanvas {
    protected ctx: CanvasRenderingContext2D = <CanvasRenderingContext2D> {} // 2d对象
    protected cacheCtx: CanvasRenderingContext2D = <CanvasRenderingContext2D> {} // 2d对象
    protected cacheCanvas: HTMLCanvasElement = <HTMLCanvasElement> {} // 人物X轴位置
    protected roleX: number = 0 // 人物X轴位置
    protected roleY: number = 0 // 人物Y轴位置
    protected roleW: number = 50 // 人物宽度
    protected roleH: number = 50 // 人物高度
    protected roleMove: number = 50 // 人物移动单元
    protected villainX: number = 800 // 反派人物X轴位置
    protected villainY: number = 800 // 反派人物Y轴位置
    protected villainXgo: boolean = true // 反派人物X轴是否可通过 -- 防止角色抱死
    protected villainYgo: boolean = true // 反派人物y轴是否可通过
    protected villainW: number = 50 // 反派人物宽度
    protected villainH: number = 50 // 反派人物高度
    protected villainMove: number = 50 // 反派人物移动单元
    protected ctxW: number = 800 // 画布宽度
    protected ctxH: number = 800 // 画布高度
    protected textureW: number = 50 // 墙纹理宽度
    protected textureH: number = 50 // 墙纹理高度
    protected wallList: wall[] = [
        {
            pointStartX: 500,
            pointStartY: 300,
            wallW: 50,
            wallH: 100,
        },
        {
            pointStartX: 100,
            pointStartY: 500,
            wallW: 50,
            wallH: 300,
        },
        {
            pointStartX: 300,
            pointStartY: 500,
            wallW: 300,
            wallH: 50,
        }
    ] // 墙体数据
	constructor(){
	}
    // 初始化
    public createCanvas(id: string) {
        const canvas = document.createElement('canvas')
        canvas.setAttribute('width', `${this.ctxW}px`)
        canvas.setAttribute('height', `${this.ctxH}px`)
        const dom = document.getElementById(id)
        if(dom) {
            dom.append(canvas)
            const ctx = canvas.getContext('2d');
            this.ctx = ctx as CanvasRenderingContext2D
        }
        // 创建临时canvas做缓冲
        const cacheCanvas = document.createElement('canvas')
        cacheCanvas.setAttribute('width', `${this.ctxW}px`)
        cacheCanvas.setAttribute('height', `${this.ctxH}px`)
        this.cacheCanvas = cacheCanvas
        this.cacheCtx = cacheCanvas.getContext('2d') as CanvasRenderingContext2D;

    }

    // 绘制所有单元
    public async drawAllUnit() {
        this.cacheCtx.clearRect(0, 0, this.ctxW, this.ctxH)
        await this.drawRole()
        await this.drawRoleTow()
        await this.drawBackgroud()
        const image = this.canvasToImg(this.cacheCanvas)
        image.onload = ()=>{
            this.ctx.clearRect(0, 0, this.ctxW, this.ctxH)
            this.ctx.rect(0, 0, this.ctxW, this.ctxH)
            this.ctx.fillStyle = '#eeeeee';
            this.ctx.fill()
            this.ctx.drawImage(image, 0, 0, this.ctxW, this.ctxH)
        }
    }

    // 画布转图片对象
    private canvasToImg(canvas: HTMLCanvasElement) {
        const img = new Image()
        img.src = canvas.toDataURL('image/png')
        return img
    }

    // 绘制角色
    public async drawRole() {
        await this.drawImageFun(role, this.roleX, this.roleY, this.roleW, this.roleH)
    }

    // 绘制角色2
    public async drawRoleTow() {
        await this.drawImageFun(role2, this.villainX, this.villainY, this.villainW, this.villainH)
    }

    /**
     * 绘制图片的方法
     * @param src 图片地址
     * @param x x坐标
     * @param y y坐标
     * @param w 宽度
     * @param h 高度
     * @returns 
     */
    private drawImageFun(src: string, x: number, y: number, w: number, h: number) {
        return new Promise((resolve, reject)=>{
            const img = new Image();   // 创建一个<img>元素
            img.onload = ()=>{
                this.cacheCtx.drawImage(img, x, y, w, h)//绘制图片
                resolve(true)
            }
            img.onerror = ()=>void reject(false);
            img.src = src; // 设置图片源地址
        })
    }

    // 绘制纹理
    private drawTexture(src: string, x: number, y: number, w: number, h: number) {
        return new Promise((resolve, reject)=>{
            const img = new Image();   // 创建一个<img>元素
            img.src = src; // 设置图片源地址
            img.onload = ()=>{
                // 固定纹理的宽高
                let tempCanvas: HTMLCanvasElement = document.createElement('canvas');
                tempCanvas.width = this.textureW;
                tempCanvas.height = this.textureH;
                let tempCtx: CanvasRenderingContext2D = tempCanvas.getContext('2d') as CanvasRenderingContext2D;
                tempCtx.drawImage(img, 0, 0, this.textureW, this.textureH);
                let pat: CanvasPattern = this.cacheCtx.createPattern(tempCanvas,"repeat") as CanvasPattern;
                this.cacheCtx.rect(x,y,w,h);
                this.cacheCtx.fillStyle = pat;
                this.cacheCtx.fill()
                resolve(true)
            }
            img.onerror = ()=>void reject(false);
        })
    }

    // 绘制场景
    public async drawBackgroud() {
        for(let i = 0; i < this.wallList.length; i++) {
            const ele = this.wallList[i]
            await this.drawTexture(wall, ele.pointStartX, ele.pointStartY, ele.wallW, ele.wallH)
        }
    }

    /**
     * 物体碰撞判断 -- 角色坐标加角色的宽高，要都小于墙体坐标或者大于墙体坐标加宽或者高
     * @param x 角色下一次移动的x坐标
     * @param y 角色下一次移动的y坐标
     * @returns 
     */
    public collisionJudge(x: number, y: number) {
        let result: boolean = true
        for(let i: number = 0; i < this.wallList.length; i++) {
            const ele = this.wallList[i]
            const pointStartX = ele.pointStartX
            const pointStartY = ele.pointStartY
            const pointEndX = ele.pointStartX + ele.wallW
            const pointEndY = ele.pointStartY + ele.wallH
            // 排除 X 轴和 Y 轴上坐标尾部贴合情况
            if(x >= pointStartX && x < pointEndX && y >= pointStartY && y < pointEndY) {
                result = false
                break;
            }
        }
        return result
    }

    // 开始角色移动
    public loadRole() {
        const that = this
        document.onkeydown = function(e){    //对整个页面监听  
            const keyNum = e || window.event || arguments.callee.caller.arguments[0];       //获取被按下的键值  
            //判断如果用户按下了回车键（keycody=13）  
            const key = keyNum.key
            console.log(key)
            if(key === 'w') {
                // 上
                if(that.roleY > 0) {
                    let roleY = Number(that.roleY) - that.roleMove
                    // 添加判断是否在墙的范围内
                    const result = that.collisionJudge(that.roleX, roleY)
                    if(!result) {
                        return
                    }
                    if(roleY < 0) {
                        roleY = 0
                    }
                    if(that.roleY !== roleY) {
                        that.roleY = roleY
                        that.drawAllUnit()
                    }
                }
            }
            if(key === 's') {
                // 下
                if(that.roleY < that.ctxH) {
                    let roleY = Number(that.roleY) + that.roleMove
                    // 添加判断是否在墙的范围内
                    const result = that.collisionJudge(that.roleX, roleY)
                    if(!result) {
                        return
                    }
                    if(roleY > that.ctxH - that.roleH) {
                        roleY = that.ctxH - that.roleH
                    }
                    if(that.roleY !== roleY) {
                        that.roleY = roleY
                        that.drawAllUnit()
                    }
                }
            }
            if(key === 'a') {
                // 左
                if(that.roleX > 0) {
                    let roleX = Number(that.roleX) - that.roleMove
                    // 添加判断是否在墙的范围内
                    const result = that.collisionJudge(roleX, that.roleY)
                    if(!result) {
                        return
                    }
                    if(roleX < 0) {
                        roleX = 0
                    }
                    if(that.roleX !== roleX) {
                        that.roleX = roleX
                        that.drawAllUnit()
                    }
                }
            }
            if(key === 'd') {
                // 右
                if(that.roleX < that.ctxW) {
                    let roleX = Number(that.roleX) + that.roleMove
                    // 添加判断是否在墙的范围内
                    const result = that.collisionJudge(roleX, that.roleY)
                    console.log(result)
                    if(!result) {
                        return
                    }
                    if(roleX > that.ctxW - that.roleW) {
                        roleX = that.ctxW - that.roleW
                    }
                    if(that.roleX !== roleX) {
                        that.roleX = roleX
                        that.drawAllUnit()
                    }
                }
            }
        }
    }

    // 反派角色 X 轴移动
    private villainMoveX() {
        // X轴移动
        if(this.roleX < this.villainX) {
            // 左
            let newX = this.villainX - this.villainMove
            const result = this.collisionJudge(newX, this.villainY)
            if(result) {
                if(newX < this.roleX) {
                    newX = this.roleX
                }
                this.villainX = newX
            } else {
                this.villainXgo = false
                // 碰撞后走Y轴移动
                if(this.villainYgo) {
                    this.villainMoveY()
                }
            }
        } else {
            // 右
            let newX = this.villainX + this.villainMove
            const result = this.collisionJudge(newX, this.villainY)
            if(result) {
                if(newX > this.roleX) {
                    newX = this.roleX
                }
                this.villainX = newX
            } else {
                this.villainXgo = false
                // 碰撞后走Y轴移动
                if(this.villainYgo) {
                    this.villainMoveY()
                }
            }
        }
    }

    // 反派角色 Y 轴移动
    private villainMoveY() {
        // Y轴移动
        if(this.roleY < this.villainY) {
            let newY = this.villainY - this.villainMove
            const result = this.collisionJudge(this.villainX, newY)
            if(result) {
                if(newY < this.roleY) {
                    newY = this.roleY
                }
                this.villainY = newY
            } else {
                this.villainYgo = false
                // 碰撞后走X轴移动
                if(this.villainXgo) {
                    this.villainMoveX()
                }
            }
        } else {
            let newY = this.villainY + this.villainMove
            const result = this.collisionJudge(this.villainX, newY)
            if(result) {
                if(newY > this.roleY) {
                    newY = this.roleY
                }
                this.villainY = newY
            } else {
                this.villainYgo = false
                // 碰撞后走X轴移动
                if(this.villainXgo) {
                    this.villainMoveX()
                }
            }
        }
    }

    // 反派角色移动
    public loadVillain() {
        // 添加逻辑 --- 判断是走X轴还是y轴
        const differenceX = Math.abs(this.villainX - this.roleX)
        const differenceY = Math.abs(this.villainY - this.roleY)
        if(differenceX > differenceY) {
            this.villainMoveX()
        } else {
            this.villainMoveY()
        }
        this.drawAllUnit()
        setTimeout(()=>{
            this.villainYgo = true
            this.villainXgo = true
            window.requestAnimationFrame(()=>this.loadVillain())
        }, 1000)
    }

    // 反派角色移动智能防止碰撞墙壁以及死路
    private anticollisionHandler() {
        // 条件，当直线碰撞时，只有单轴差距 -- 中途撞墙判断 -- 获取墙体信息，优先走出墙体范围，定义新的终点，到达终点后重新以目标为终点
        // 情况：上述途中目标走动时不成立
        // 情况：上述移动中从哪一边移动过去
        // 结果：此效果暂无法达成
    }
}